#include "../include/ApiHandler.hpp"
#include "../include/DatabasePool.hpp"
#include "../include/AuthTypes.hpp"
#include "../include/AuthHandler.hpp"
#include "../include/DBUtil.hpp"
#include "../include/MenuHandler.hpp"
#include "../include/OrderHandler.hpp"

#include <httplib.h>
#include <json/json.h>
#include <memory>
#include <fstream>
#include <sstream>

using namespace httplib;
using namespace std;
using namespace Json;
// 同ApiHandler一样的处理方式
using DatabasePool = ConnectionPool;

// 添加CORS头到响应
void addCorsHeaders(Response& res) {
    // 生产环境应替换为具体的前端域名，例如 "https://your-frontend-domain.com"
    res.set_header("Access-Control-Allow-Origin", "*");
    res.set_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    res.set_header("Access-Control-Allow-Headers", "Content-Type, Authorization");
    res.set_header("Access-Control-Allow-Credentials", "true");
}

// 处理预检请求(OPTIONS)
void handleOptionsRequest(const Request& req, Response& res) {
    addCorsHeaders(res);
    res.status = 204; // No Content
}

// 加载配置文件
/**
 * @brief 从指定的文件路径加载JSON配置
 * 		通过 ifstream 打开配置文件，如果无法打开则抛出异常
 * 		使用 stringstream 和 Json::parseFromStream 来读取和解析JSON内容，若解析失败抛出异常
 * @return  类型: class Json::Value
 */
Value loadConfig(const string& path) {
    // 解析配置文件的JSON格式内容
    ifstream configFile(path);
    // 打不开就给异常
    if (!configFile.is_open()) throw runtime_error("无法打开配置文件: " + path);

    // 打得开 就读取文件内容
    stringstream buf;
    buf << configFile.rdbuf();

    // JSON对象存配置内容
    Value config;
    // 解析器
    CharReaderBuilder reader;
    JSONCPP_STRING errs;    // 错误信息

    // 解析JSON 解析不了就抛异常
    if (!parseFromStream(reader, buf, &config, &errs)) throw runtime_error("配置文件解析错误: " + errs);

    return config;
}

// 注册路由 处理
/**
 * @brief 创建不同的请求处理器（如认证、菜单、订单）实例，每个处理器负责不同的功能。
 * 		从ApiHandler 继承的每一项 都和 路由联动
 * 		为每个路由配置相应的处理函数
 * @param ：class httplib::Server
 * @param ：using DatabasePool = ConnectionPool
 * 			class ConnectionPool
 * MySQL数据库连接池类（单例模式）
 * 通过复用数据库连接减少TCP握手和连接认证开销，提高高并发场景下的数据库访问性能。 线程安全，支持动态扩容和空闲连接回收。
 */
void setupRoutes(Server& server, DatabasePool& pool) {
    // 添加根路径和/api路径的健康检查
    server.Get("/", [](const Request& req, Response& res) {
        addCorsHeaders(res);
        res.set_content("Food Order Server is running", "text/plain");
    });

    server.Get("/api", [](const Request& req, Response& res) {
        addCorsHeaders(res);
        Json::Value response;
        response["status"] = "active";
        response["version"] = "1.0.0";
        response["available_apis"] = Json::arrayValue;
        response["available_apis"].append("/api/auth");
        response["available_apis"].append("/api/menu");
        response["available_apis"].append("/api/orders");
        res.set_content(response.toStyledString(), "application/json");
    });

    auto authHandler = make_shared<AuthHandler>(pool);
    auto menuHandler = make_shared<MenuHandler>(pool);
    auto orderHandler = make_shared<OrderHandler>(pool);

    // 使用模板Lambda处理不同类型Handler（C++17特性）
    auto registerRoute = [&server]<typename T>(
        const char* method, 
        const string& path,
        const shared_ptr<T>& handler,
        void (T::*func)(const Request&, Response&)) 
    {
        server.Options(path, handleOptionsRequest);

        // 使用if constexpr优化编译时判断（C++17）
        if constexpr (std::is_same_v<decltype(method), const char*>) {
            if (strcmp(method, "Get") == 0) {
                server.Get(path, [=](const Request& req, Response& res) {
                    addCorsHeaders(res);
                    ((*handler).*func)(req, res);
                });
            }
            else if (strcmp(method, "Post") == 0) {
                server.Post(path, [=](const Request& req, Response& res) {
                    addCorsHeaders(res);
                    ((*handler).*func)(req, res);
                });
            }
            else if (strcmp(method, "Put") == 0) {
                server.Put(path, [=](const Request& req, Response& res) {
                    addCorsHeaders(res);
                    ((*handler).*func)(req, res);
                });
            }
        }
    };

    // 认证路由
    registerRoute("Post", "/api/auth/register", authHandler, &AuthHandler::registerUser);
    registerRoute("Post", "/api/auth/login", authHandler, &AuthHandler::login);
    registerRoute("Post", "/api/auth/logout", authHandler, &AuthHandler::logout);

    // 菜单路由
    registerRoute("Get", "/api/menu/categories", menuHandler, &MenuHandler::getCategories);
    registerRoute("Get", "/api/menu/dishes", menuHandler, &MenuHandler::getDishes);
    registerRoute("Get", "/api/menu/dishes/(\\d+)", menuHandler, &MenuHandler::getDishDetails);
    registerRoute("Post", "/api/menu/dishes", menuHandler, &MenuHandler::addDish);
    registerRoute("Put", "/api/menu/dishes/stock", menuHandler, &MenuHandler::updateDishStock);

    // 订单路由
    registerRoute("Post", "/api/orders", orderHandler, &OrderHandler::createOrder);
    registerRoute("Get", "/api/orders/history", orderHandler, &OrderHandler::getOrderHistory);

    // 添加404处理
    server.set_error_handler([](const Request& req, Response& res) {
        if (res.status == 404) {
            Json::Value error;
            error["error"] = "Not Found";
            error["message"] = "The requested resource was not found";
            error["available_endpoints"] = Json::arrayValue;
            error["available_endpoints"].append("/api/auth");
            error["available_endpoints"].append("/api/menu");
            error["available_endpoints"].append("/api/orders");
            res.set_content(error.toStyledString(), "application/json");
        }
    });
}

// 最后一步 做好各类初始化 启动服务器 
void start() {    
    // 传config这一json格式的配置文件
    auto config = loadConfig("./config/config.json");

    // 调用连接池相关
    // 将数据库配置文件与连接池所需参数匹配
    // 先初始化
    auto& dbPool = *ConnectionPool::getInstance();
    // 调用init 然后做参数匹配
    /**
     * void ConnectionPool::init(const std::string &host, const std::string &user, const std::string &pwd, const std::string &dbname, unsigned int port = 3306U, int maxConn = 10, int timeout = 5000)
     */
    dbPool.init(
        config["database"]["host"].asString(),         // 主机名
        config["database"]["username"].asString(),     // 数据库用户名
        config["database"]["password"].asString(),     // 数据库密码
        config["database"]["database"].asString(),     // 数据库名
        config["database"]["port"].asUInt(),           // 数据库端口
        config["database"]["pool_size"].asInt(),       // 连接池大小
        5000 // 连接超时时间，单位为毫秒
    );

    // 创建http服务器
    Server server;

    // 给路由
    setupRoutes(server, dbPool);

    // 配置端口
    int port = config["server"]["port"].asInt();
    cout << "服务器已启动 监听端口号: " << port << endl;

    // 启动服务器就要监听 IP 地址上对应的端口
    if (!server.listen("0.0.0.0", port)) {
        throw runtime_error("Failed to start server on port " + to_string(port));
    }
}

int main() {
    try {
        start();
    } catch (const exception& e) {
        // 如果发生异常，输出错误信息并返回1
        cerr << "服务器错误: " << e.what() << endl;
        return 1;
    }
    return 0;
}